package com.tagtraum.perf.gcviewer;


import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.border.Border;

public abstract class SectionCellRenderer extends JLabel
  implements ListCellRenderer
{
  private static final Color BORDER_COLOUR = Color.decode("#cccccc");
  private static final Color SELECTED_BACKGROUND_COLOUR = Color.decode("#e6e6e6");
  private static final Color INACTIVE_COLOUR = Color.decode("#666666");
  private static final Color ACTIVE_COLOUR = Color.decode("#172944");
  private static final int GAP = 5;
  private static final int LEFT_GAP = 15;
  private static final int INDENTED_LEFT_GAP = 27;
  private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(5, 15, 5, 5);
  private static final Border LEFT_INDENT = BorderFactory.createEmptyBorder(5, 27, 5, 5);
  private static final Border BOTTOM_LINE = BorderFactory.createMatteBorder(0, 0, 1, 0, BORDER_COLOUR);

  private static final ImageIcon TICK = loadIcon("Tick_12x12.png");
  private static final ImageIcon CROSS = loadIcon("Cross_12x12.png");
  private static final ImageIcon INFO = loadIcon("Info_12x12.png");
  private final boolean requiresBorder;

  protected abstract Font headingFont();

  protected abstract Font regularFont();

  protected abstract Color getHeadingColour();

  private static ImageIcon loadIcon(String path)
  {
    try
    {
      BufferedImage image = ImageIO.read(SectionCellRenderer.class.getResource(path));
      return new ImageIcon(image);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static SectionCellRenderer create(boolean isLarge) {
    if (isLarge) {
      return new LargeSectionCellRenderer();
    }
    return new RegularSectionCellRenderer();
  }

  protected SectionCellRenderer(boolean requiresBorder) {
    this.requiresBorder = requiresBorder;

    setOpaque(true);
  }

  public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
  {
    Section section = (Section)value;
    setText(section.getName());
    updateFont(section);
    updateForeground(isSelected, section);
    updateBackground(isSelected, section.isHeading());
    updateIcon(section);
    updateBorder(section);
    return this;
  }

  private void updateFont(Section section) {
    Font font = section.isHeading() ? headingFont() : regularFont();
    setFont(font);
  }

  private void updateForeground(boolean isSelected, Section section) {
    if (section.isHeading())
      setForeground(getHeadingColour());
    else if (isSelected)
      setForeground(ACTIVE_COLOUR);
    else
      setForeground(INACTIVE_COLOUR);
  }

  private void updateBorder(Section section)
  {
    boolean needsIndent = (!section.isAnalyticView()) && (!section.isHeading());
    Border border = needsIndent ? LEFT_INDENT : EMPTY_BORDER;

    if ((this.requiresBorder) && (section.isLastInGroup())) {
      border = BorderFactory.createCompoundBorder(BOTTOM_LINE, border);
    }

    setBorder(border);
  }

  private void updateBackground(boolean isSelected, boolean isHeading) {
    Color background = (isSelected) && (!isHeading) ? SELECTED_BACKGROUND_COLOUR : Color.WHITE;
    setBackground(background);
  }

  private void updateIcon(Section section) {
    if (!section.isAnalyticView()) {
      setIcon(null);
    } else if (section.getLevel() == WarningSeverityLevel.ADVICE) {
      setIcon(INFO);
    } else {
      ImageIcon icon = section.isOn() ? CROSS : TICK;
      setIcon(icon);
    }
  }
}